package fr.neyb.wesb.core.job;

import fr.neyb.framework.observer.Observable;
import fr.neyb.framework.observer.Observer;
import fr.neyb.wesb.core.data.io.RecordReader;
import fr.neyb.wesb.core.data.io.RecordWriter;
import fr.neyb.wesb.core.job.runner.JobsRunner;

/**
 * identified a task. a Job has inputs and output. a Job go throught
 * {@link RunningState RunningStates}.
 * 
 * @author adeconin
 * 
 */
public interface Job extends Observable, Observer {

	/**
	 * ask the jobRunner to run the Job (id. to run run(this))<br/>
	 * when the Jobrunner finished the job run, he's gonna call his dependencies
	 * job's start method.
	 * 
	 * @param runner
	 *            the runner that will run the job
	 */
	void start(JobsRunner runner);

	/**
	 * ask to run the job in the current task <br/>
	 * <b>this method should only be used by a jobrunner.</b><br/>
	 * this method should ed with calling all dependencies of this the method
	 * {@linkplain #start start(runner)}
	 * 
	 * @param runner
	 *            the runner that will run dependencies jobs
	 */
	void run(JobsRunner runner);

	/**
	 * add a dependence to the job. this means the current job can not run
	 * before all his dependencies are in state ENDED
	 * 
	 * @param dependence
	 *            dependence to add
	 * 
	 * @return true if dependence wasn't already present
	 */
	boolean addDependency(Job dependence);

	/**
	 * allow to set a state to hte job
	 * 
	 * @param newState
	 *            the new state of the job.
	 */
	void setState(RunningState newState);

	/**
	 * allow to get the state of the job
	 * 
	 * @return the current state of the job
	 */
	RunningState getState();

	/**
	 * set a reader of the job. if reader is null this means the reader is
	 * unset. a job can't be run before all his readers are set.
	 * 
	 * @param i
	 *            index of the reader (0 to number of readers -1)
	 * @param reader
	 *            the new reader
	 * @return true if the reader has changed
	 * @throws NullPointerException
	 *             if i is strictly negative or superior (or equals) to number
	 *             of allowed readers
	 */
	boolean setReader(int i, RecordReader reader);

	/**
	 * set a reader of the job. if writer is null this means the writer is
	 * unset. a job can't be run before all his writer are set.
	 * 
	 * @param i
	 *            index of the writer (0 to number of readers -1)
	 * @param reader
	 *            the new writer
	 * @return true if the writer has changed
	 * @throws NullPointerException
	 *             if i is strictly negative or superior (or equals) to number
	 *             of allowed readers
	 */
	boolean setWriter(int i, RecordWriter writer);

}
